<template >
	<div>
		<!-- 面包屑导航 -->
		<el-breadcrumb separator-class="el-icon-arrow-right">
			<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
			<el-breadcrumb-item>角色管理</el-breadcrumb-item>
			<el-breadcrumb-item>角色列表</el-breadcrumb-item>
		</el-breadcrumb>
		<!-- 卡片视图>栅格系统包含搜索 -->
		<el-card class="box-card">
			<el-button type="primary" @click="addRoleDialogVisible=true">添加角色</el-button>
			<el-table :data="roleList" border stripe style="width: 100%">
				<el-table-column type="expand">
					<template slot-scope="scope">
						<el-row
							:class="['bb',index1==0?'bt':'']"
							v-for="(item1,index1) in scope.row.children22"
							:key="item1.id"
						>
							<!-- 渲染一级权限 -->
							<el-col :span="4">
								<el-tag closable @close="removeRightById(scope.row,item1.id)">{{item1.authName}}</el-tag>
								<i class="el-icon-caret-right"></i>
							</el-col>
							<!-- 渲染二级和三级权限 -->
							<el-col :span="20">
								<!-- 渲染二级模板 -->
								<el-row
									:class="[index2==0?'':'bt']"
									v-for="(item2,index2) in item1.children22"
									:key="item2.id"
								>
									<!-- 渲染二级权限 -->
									<el-col :span="5">
										<el-tag
											closable
											type="success"
											@close="removeRightById(scope.row,item2.id)"
										>{{item2.authName}}</el-tag>
										<i class="el-icon-caret-right"></i>
									</el-col>
									<el-col :span="19" :class="['co']">
										<el-tag
											closable
											type="warning"
											v-for="item3 in item2.children22"
											:key="item3.id"
											@close="removeRightById(scope.row,item3.id)"
										>{{item3.authName}}</el-tag>
									</el-col>
								</el-row>
							</el-col>
						</el-row>
					</template>
				</el-table-column>
				<el-table-column type="index" :index="index" width="50"></el-table-column>
				<el-table-column label="角色名称" prop="roleName"></el-table-column>
				<el-table-column label="角色描述" prop="roleDesc"></el-table-column>
				<el-table-column label="操作">
					<template slot-scope="scope">
						<el-button
							type="primary"
							size="mini"
							icon="el-icon-edit"
							@click="showEditRoleDialog(scope.row.id)"
						>编辑</el-button>
						<el-button
							type="danger"
							size="mini"
							icon="el-icon-delete"
							@click="deleteRole(scope.row.id)"
						>删除</el-button>
						<el-button
							type="warning"
							size="mini"
							icon="el-icon-setting"
							@click="showSetRoleDialog(scope.row)"
						>分配角色</el-button>
					</template>
				</el-table-column>
			</el-table>

			<!-- 添加角色对话框 -->
			<el-dialog
				title="添加角色"
				:visible.sync="addRoleDialogVisible"
				width="50%"
				@close="resetAddRoleForm"
			>
				<el-form :rules="addRoleRules" ref="addRoleFormRef" :model="addRoleForm" label-width="80px">
					<el-form-item label="角色名称" prop="roleName">
						<el-input v-model="addRoleForm.roleName"></el-input>
					</el-form-item>
					<el-form-item label="角色描述" prop="roleDesc">
						<el-input v-model="addRoleForm.roleDesc"></el-input>
					</el-form-item>
				</el-form>
				<span slot="footer" class="dialog-footer">
					<el-button @click="addRoleDialogVisible = false">取 消</el-button>
					<el-button type="primary" @click="addRole">确 定</el-button>
				</span>
			</el-dialog>

			<!-- 编辑角色对话框 -->
			<el-dialog
				title="编辑角色"
				:visible.sync="editRoleDialogVisible"
				width="50%"
				@close="resetEditRoleForm"
			>
				<el-form :rules="addRoleRules" ref="editRoleFormRef" :model="editRoleForm" label-width="80px">
					<el-form-item label="角色名称" prop="roleName">
						<el-input v-model="editRoleForm.roleName"></el-input>
					</el-form-item>
					<el-form-item label="角色描述" prop="roleDesc">
						<el-input v-model="editRoleForm.roleDesc"></el-input>
					</el-form-item>
				</el-form>
				<span slot="footer" class="dialog-footer">
					<el-button @click="editRoleDialogVisible = false">取 消</el-button>
					<el-button type="primary" @click="editRole(editRoleForm.roleId)">确 定</el-button>
				</span>
			</el-dialog>

			<!-- 分配角色对话框 -->
			<el-dialog
				title="分配角色"
				:visible.sync="setRoleDialogVisible"
				width="50%"
				@close="clearDefaultCheckedKeys"
			>
				<el-tree
					:data="rightList"
					show-checkbox
					node-key="id"
					:default-expand-all="true"
					:props="treeProps"
					:default-checked-keys="defaultCheckedKey"
					ref="treeRef"
				></el-tree>
				<span slot="footer" class="dialog-footer">
					<el-button @click="setRoleDialogVisible = false">取 消</el-button>
					<el-button type="primary" @click="allowRights">确 定</el-button>
				</span>
			</el-dialog>
		</el-card>
	</div>
</template>

<script>
	export default {
		data() {
			return {
				index: 1,
				roleList: [],
				rightList: [],
				setRoleDialogVisible: false,
				treeProps: {
					children: "children",
					label: "authName"
				},
				addRoleDialogVisible: false,
				addRoleForm: {
					roleName: "",
					roleDesc: ""
				},
				addRoleRules: {
					roleName: [
						{ required: true, message: "请输入角色名称", trigger: "blur" },
						{ min: 3, max: 16, message: "有效长度3--16", trigger: "blur" }
					]
				},
				editRoleDialogVisible: false,
				editRoleForm: {
					roleName: "",
					roleDesc: ""
				},
				defaultCheckedKey: [105, 116],
				roleId: ""
			};
		},
		created() {
			this.getRolesList();
		},
		methods: {
			// 获取角色列表
			async getRolesList() {
				let { data: res } = await this.$http.get("roles");
				// console.log(res);
				if (res.meta.status !== 200)
					return this.$message.error("获取角色列表失败");
				this.$message.success("获取角色列表成功");

				// 将对象中的children属性全部改名////////////////////////////////////////////////////
				let newData = JSON.parse(
					JSON.stringify(res.data).replace(/children/g, "children22")
				);
				// this.roleList = res.data;
				this.roleList = newData;
			},
			// 移除权限
			async removeRightById(role, rightId) {
				let confirmResult = await this.$confirm(
					"此操作将永久删除该文件, 是否继续?",
					"提示",
					{
						confirmButtonText: "确定",
						cancelButtonText: "取消",
						type: "warning"
					}
				).catch(err => err);
				// console.log(confirmResult);
				if (confirmResult == "cancel") return this.$message.error("取消了刪除");

				// 删除角色指定权限 请求路径：roles/:roleId/rights/:rightId
				let { data: res } = await this.$http.delete(
					`roles/${role.id}/rights/${rightId}`
				);
				if (res.meta.status !== 200) return this.$message.error("刪除權限失敗");

				// this.getRolesList();  // 此方法每次都會讓頁面重新刷新,用戶體驗不好
				role.children = res.data;
			},
			// 显示分配权限对话框
			async showSetRoleDialog(role) {
				let { data: res } = await this.$http.get("rights/tree");
				// console.log(res);
				this.rightList = res.data;

				// 将当前用户id保存到数据中
				this.roleId = role.id;
				console.log(role);
				// 递归获取三级节点的id/////////////////////////////////////
				this.getLeafKeys(role, this.defaultCheckedKey);
				this.setRoleDialogVisible = true;
			},
			// 通过递归的形式,获取角色下所有三级权限的id, 并保存到defaultCheckedKey数组中
			getLeafKeys(node, arr) {
				// 如果当前的 node 节点不包含children属性,则是三级节点
				// 先写   递归的终止条件
				if (!node.children) return arr.push(node.id);
				// 递归调用
				node.children.forEach(item => this.getLeafKeys(item, arr));
			},
			resetAddRoleForm() {
				this.$refs.addRoleFormRef.resetFields();
			},
			clearDefaultCheckedKeys() {
				this.defaultCheckedKey = [];
			},
			// 错误示范
			// addRole() {
			// 	this.$refs.addRoleFormRef.validate(async valid => {
			// 		if (!valid) return this.$message.error("请输入有效角色名");

			// 		console.log(111);
			// 		console.log(this.addRoleForm);
			// 		let { data: res } = await this.$http.post("roles", this.addRoleForm);
			// 		console.log(res);
			// 		// if (res.meta.status !== 201) return this.$message.error("添加角色失败");
			// 		console.log(2222);
			// 		// this.$message.success("添加角色成功");
			// 	});
			// 	console.log(3333333);

			// 	this.addRoleDialogVisible = false;
			// 放在请求函数外面,导致异步函数未执行,此代码就执行,导致请求参数为空,
			// }
			addRole() {
				this.$refs.addRoleFormRef.validate(async valid => {
					if (!valid) return this.$message.error("请输入有效的角色名");
					let { data: res } = await this.$http.post("roles", this.addRoleForm);
					// console.log(res);
					if (res.meta.status !== 201) return this.$message.error("添加角色失败");
					this.$message.success("添加用户成功");
					this.getRolesList();
					this.addRoleDialogVisible = false;
				});
			},
			resetEditRoleForm() {
				this.$refs.editRoleFormRef.resetFields();
			},
			async showEditRoleDialog(id) {
				// console.log(id);
				let { data: res } = await this.$http.get("roles/" + id);
				// console.log(res);
				this.editRoleForm = res.data;
				this.editRoleDialogVisible = true;
			},
			editRole(id) {
				// console.log(id);
				this.$refs.editRoleFormRef.validate(async valid => {
					if (!valid) return this.$message.error("角色格式不正确");
					let { data: res } = await this.$http.put(
						"roles/" + id,
						this.editRoleForm
					);
					if (res.meta.status !== 200) return this.$message.error("修改角色失败");
					this.$message.success("修改用户成功");
					this.getRolesList();
					this.editRoleDialogVisible = false;
				});
			},
			async deleteRole(id) {
				let result = await this.$confirm(
					"此操作将永久删除该文件, 是否继续?",
					"提示",
					{
						confirmButtonText: "确定",
						cancelButtonText: "取消",
						type: "warning"
					}
				).catch(err => err);
				// console.log(result);
				if (result === "cancel") return this.$message.error("取消删除角色");
				let { data: res } = await this.$http.delete("roles/" + id);
				// console.log(res);
				if (res.meta.status !== 200) return this.message.error("删除角色失败");
				this.$message.success("删除角色成功");

				this.getRolesList();
			},
			async allowRights() {
				let keys = [
					...this.$refs.treeRef.getCheckedKeys(),
					...this.$refs.treeRef.getHalfCheckedKeys()
				];
				// console.log(keys);
				let idStr = keys.join(",");
				let { data: res } = await this.$http.post(`roles/${this.roleId}/rights`, {
					rids: idStr
				});
				// console.log(res.data);

				if (res.meta.status !== 200) return this.message.error("分配角色失败");
				this.$message.success("分配角色成功");

				this.getRolesList();
				this.setRoleDialogVisible = false;
			}
		}
	};
</script>

<style lang="less" scoped>
	.el-tag {
		margin: 10px;
	}
	.bt {
		border-top: 1px solid #0f0;
	}
	.bb {
		border-bottom: 1px solid #0f0;
	}
	.el-row {
		display: flex;
		align-items: center;
		border-left: 1px solid #0f0;
	}
	.co {
		border-left: 1px solid #0f0;
	}
</style>